.486p
.model flat
.code

include 6502.h
include equates.h
include debug.h
include file.h
include data.h
include ppu.h
include empty.h
include main.h

public malloc
public malloctmp
public free
public empty_R
public empty_W
public void
public ram_R
public sram_R
public ram_W
public sram_W
public rom_R
;----------------------------------------------------------------------------
malloc:;        get mem from heap
;       in:     edi=size
;       out:    edi=pointer
;               c=1 on error with edi=0
;
;heap is filled with used or unused chunks of mem.  each is preceded by a 8
;byte header: +0 dword- size in bytes (including header). +4 byte-
;bit 0=used; bit 1=last chunk
;----------------------------------------------------------------------------
        push eax
        push esi
        add edi,16                      ;enough space to split chunk in two
        mov esi,offset heap
mal1:
        cmp edi,[esi]                   ;too big?
        ja mal2
        test byte ptr [esi+4],1         ;used?
        jz mal0
mal2:   test byte ptr [esi+4],2         ;last chunk?
        jnz mal9
        add esi,[esi]                   ;move to next chunk
        jmp mal1
mal0:
        sub edi,8
        mov eax,[esi]           ;eax=old size
        mov [esi],edi           ;resize
        sub eax,edi             ;eax=remainder size
        add edi,esi             ;edi=remainder ptr
        mov [edi],eax
        mov byte ptr [esi+4],1
        mov byte ptr [edi+4],0
        lea edi,[esi+8]
        pop esi
        pop eax
        clc
        ret
mal9:        
        if DEBUG
                mov al,6
                jmp _error
        else
                pop esi
                pop eax
                xor edi,edi
                stc
        endif
        ret
;----------------------------------------------------------------------------
malloctmp:;     find largest unused chunk
;       out:    ecx=size, edi=ptr
;----------------------------------------------------------------------------
        push esi
        xor ecx,ecx
        mov esi,offset heap
mtmp0:
        add esi,[esi]
        test byte ptr [esi+4],1
        jnz mtmp1
        cmp ecx,[esi]
        ja mtmp1
        mov ecx,[esi]
        lea edi,[esi+8]
mtmp1:  test byte ptr [esi+4],2
        jz mtmp0
        sub ecx,8
        pop esi
        ret
;----------------------------------------------------------------------------
free:;          deallocate heap space
;       in:     edi=ptr
;       out:    edi=0, eax,esi,ebp=?
;----------------------------------------------------------------------------
        sub edi,8
        mov esi,offset heap
free1:                          ;find ptr:
        cmp edi,esi
        jb free99                       ;out of range
        je free0                        ;got it!
        test byte ptr [esi+4],2         ;end?
        jnz free99
        mov ebp,esi             ;ebp=previous
        add esi,[esi]                   ;next chunk
        jmp free1
free0:                          ;edi=this
        add esi,[esi]           ;esi=next
        mov byte ptr [edi+4],0  ;mark this unused
        test byte ptr [ebp+4],1 ;previous unused?
        jnz free2
        mov eax,[edi]                   ;merge previous+this
        add [ebp],eax
        mov edi,ebp                     ;this=previous
free2:
        test byte ptr [esi+4],1
        jnz free9               ;next unused?
        mov eax,[esi]
        add [edi],eax                   ;merge this+next
if DEBUG
  free9:
        xor edi,edi
        ret
  free99:
        mov al,5
        jmp _error
else
  free9:
  free99:
        xor edi,edi
        ret
endif
;----------------------------------------------------------------------------
empty_R:;       read invalid memory address (error)
;----------------------------------------------------------------------------
if DEBUG
        or [int_flags],DEBUG2                   ;enter debugger
        mov [debugmsg],offset msg43             ;bad read debug msg
endif
        mov al,0 ;VS excitebike
        ret
;----------------------------------------------------------------------------
empty_W:;       write invalid memory address (error)
;----------------------------------------------------------------------------
if DEBUG
        or [int_flags],DEBUG2                   ;enter debugger
        mov [debugmsg],offset msg44             ;bad write debug msg
endif
        ret
;----------------------------------------------------------------------------
void:;          empty function
;----------------------------------------------------------------------------
        ret
;----------------------------------------------------------------------------
ram_R:;         ram read ($0000-$1FFF)
;----------------------------------------------------------------------------
        and edi,07ffh
        mov al,fs:[edi]
        ret
;----------------------------------------------------------------------------
ram_W:;         ram write ($0000-$1FFF)
;----------------------------------------------------------------------------
        and edi,07ffh
        mov fs:[edi],al
        ret
;----------------------------------------------------------------------------
sram_R:;        sram read ($6000-$7FFF)
;----------------------------------------------------------------------------
        mov al,fs:[edi]
        ret
;----------------------------------------------------------------------------
sram_W:;        sram write ($6000-$7FFF)
;----------------------------------------------------------------------------
        mov fs:[edi],al
        ret
;----------------------------------------------------------------------------
rom_R:;         rom read ($8000-$FFFF)
;----------------------------------------------------------------------------
        mov eax,edi
        shr eax,13
        mov eax,[memmap+eax*4]
        mov al,[edi+eax]
        ret
;----------------------------------------------------------------------------
        end
